// Copyright 2019 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: public_member_api_docs

import 'dart:async';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:video_player/video_player.dart';
import 'package:file_picker/file_picker.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Video Player',
      home: MyHomePage(title: 'Video Player'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  VideoPlayerController _controller;
  VideoPlayerController _toBeDisposed;
  String _retrieveDataError;

  // Video play list's data
  List<File> videoList = [];

  final ImagePicker _picker = ImagePicker();

  // 添加视频文件
  void _onVideoBtnPressed(ImageSource source) async {
    File file;

    if (source == ImageSource.camera) {
      PickedFile recordedFile = await _picker.getVideo(
          source: ImageSource.camera, maxDuration: const Duration(seconds: 10));
      file = File(recordedFile.path);
    } else {
      file = await FilePicker.getFile(type: FileType.video);
    }

    if (file != null) {
      videoList.add(file);
      setState(() {});
    }
  }

  // 清空播放列表
  void _onResetBtnPressed(BuildContext context) async {
    bool delete = await _showResetConfirmDialog(context);
    if (delete == true) {
      videoList.removeRange(0, videoList.length);
      _disposeVideoController();
      if (mounted) {
        setState(() {});
      }
    }
  }

  // 确认对话框
  Future<bool> _showResetConfirmDialog(BuildContext context) {
    return showDialog<bool>(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: Text("提示"),
          content: Text("确定要清空当前列表吗?"),
          actions: <Widget>[
            FlatButton(
              child: Text("取消"),
              onPressed: () => Navigator.of(context).pop(), // 关闭对话框
            ),
            FlatButton(
              child: Text("确认"),
              onPressed: () {
                //关闭对话框并返回true
                Navigator.of(context).pop(true);
              },
            ),
          ],
        );
      },
    );
  }

  Future<void> _playVideo(File file) async {
    if (file != null && mounted) {
      await _disposeVideoController();
      _controller = VideoPlayerController.file(File(file.path));
      await _controller.setVolume(1.0);
      await _controller.initialize();
      _controller.addListener(() {
        setState(() {});
      });
      // await _controller.setLooping(true);
      await _controller.play();
    }
  }

  Widget _previewVideo() {
    final Text retrieveError = _getRetrieveErrorWidget();
    if (retrieveError != null) {
      return retrieveError;
    }
    if (videoList.isEmpty) {
      return const Padding(
          padding: const EdgeInsets.only(top: 16.0),
          child: Text(
            'Click button to add video file.',
            textAlign: TextAlign.center,
            style: TextStyle(color: Colors.grey),
          ));
    }
    if (_controller == null) {
      return const Padding(
          padding: const EdgeInsets.only(top: 16.0),
          child: Text(
            'Choose a video from the list below.',
            textAlign: TextAlign.center,
            style: TextStyle(color: Colors.grey),
          ));
    } else {
      return AspectRatioVideo(_controller);
    }
  }

  @override
  void deactivate() {
    if (_controller != null) {
      _controller.setVolume(0.0);
      _controller.pause();
    }
    super.deactivate();
  }

  @override
  void dispose() {
    _disposeVideoController();
    super.dispose();
  }

  Future<void> _disposeVideoController() async {
    if (_toBeDisposed != null) {
      // 释放资源
      await _toBeDisposed.dispose();
    }
    _toBeDisposed = _controller;
    await _toBeDisposed?.setVolume(0);
    await _toBeDisposed?.pause();
    _controller = null;
  }

  Future<void> retrieveLostData() async {
    final LostData response = await _picker.getLostData();
    if (response.isEmpty) {
      return;
    }
    if (response.file != null) {
      if (response.type == RetrieveType.video) {
        await _playVideo(File(response.file.path));
      } else {
        print("Not video");
      }
    } else {
      _retrieveDataError = response.exception.code;
    }
  }

  Widget _buildPlayListItem(int index) {
    File file = File(videoList[index].path);
    int len = file.lengthSync();
    return ListTile(
      title: Text(file.path.substring(file.path.lastIndexOf('/') + 1)),
      subtitle: Text('大小： $len Bytes'),
      onTap: () async {
        await _playVideo(videoList[index]);
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.blueGrey,
        centerTitle: true,
        title: Text(widget.title),
      ),
      body: ListView(children: <Widget>[
        _previewVideo(),
        Divider(),
        ListView.separated(
            shrinkWrap: true,
            physics: NeverScrollableScrollPhysics(),
            itemBuilder: (BuildContext context, int index) {
              return Dismissible(
                onDismissed: (_) {
                  videoList.removeAt(index);
                  setState(() {});
                },
                movementDuration: Duration(milliseconds: 100),
                key: Key(videoList[index].path),
                child: _buildPlayListItem(index),
                background: Container(color: Colors.grey),
              );
            },
            separatorBuilder: (BuildContext context, int index) => Divider(),
            itemCount: videoList.isNotEmpty ? videoList.length : 0),
      ]),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          FloatingActionButton(
            backgroundColor: Colors.red,
            onPressed: () {
              _onVideoBtnPressed(ImageSource.gallery);
            },
            heroTag: 'video0',
            tooltip: 'Pick Video from gallery',
            child: const Icon(Icons.video_library),
          ),
          Padding(
              padding: const EdgeInsets.only(left: 16.0),
              child: FloatingActionButton(
                backgroundColor: Colors.red,
                onPressed: () {
                  _onVideoBtnPressed(ImageSource.camera);
                },
                heroTag: 'video1',
                tooltip: 'Take a Video',
                child: const Icon(Icons.videocam),
              )),
          Padding(
              padding: const EdgeInsets.only(left: 16.0),
              child: FloatingActionButton(
                backgroundColor: Colors.grey,
                onPressed: () {
                  _onResetBtnPressed(context);
                },
                heroTag: 'reset',
                tooltip: 'Clear the list',
                child: const Icon(Icons.clear),
              )),
        ],
      ),
    );
  }

  Text _getRetrieveErrorWidget() {
    if (_retrieveDataError != null) {
      final Text result = Text(_retrieveDataError);
      _retrieveDataError = null;
      return result;
    }
    return null;
  }
}

// 用AspectRatio控件包含VideoPlayer用于缩放大小
class AspectRatioVideo extends StatefulWidget {
  AspectRatioVideo(this.controller);

  final VideoPlayerController controller;

  @override
  AspectRatioVideoState createState() => AspectRatioVideoState();
}

class AspectRatioVideoState extends State<AspectRatioVideo> {
  @override
  Widget build(BuildContext context) {
    VideoPlayerController controller = widget.controller;
    if (controller.value.initialized) {
      return Container(
        padding: const EdgeInsets.all(10),
        child: AspectRatio(
          aspectRatio: controller.value?.aspectRatio,
          child: Stack(
            alignment: Alignment.bottomCenter,
            children: <Widget>[
              Stack(
                children: <Widget>[
                  VideoPlayer(controller),
                  AnimatedSwitcher(
                    duration: Duration(milliseconds: 50),
                    reverseDuration: Duration(milliseconds: 200),
                    child: controller.value.isPlaying
                        ? SizedBox.shrink()
                        : Container(
                            color: Colors.black26,
                            child: Center(
                              child: Icon(
                                Icons.play_arrow,
                                color: Colors.white,
                                size: 100.0,
                              ),
                            ),
                          ),
                  ),
                  GestureDetector(
                    onTap: () {
                      controller.value.isPlaying
                          ? controller.pause()
                          : controller.play();
                      setState(() {});
                    },
                  ),
                ],
              ),
              VideoProgressIndicator(
                controller,
                allowScrubbing: true,
              ),
            ],
          ),
        ),
      );
    } else {
      return Container();
    }
  }
}
